package com.koala.aideddevsystemmodule.modules.cacheBreakdown.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koala.aideddevsystemmodule.modules.cacheBreakdown.dao.CacheBreakdownDao;
import com.koala.aideddevsystemmodule.modules.cacheBreakdown.entity.CacheBreakdownEntity;
import com.koala.aideddevsystemmodule.modules.cacheBreakdown.service.CacheBreakdownService;
import com.koala.aideddevsystemmodule.utils.PageUtils;
import com.koala.aideddevsystemmodule.utils.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Create by koala on 2022-08-22 21:58:38
 */
@Service("cacheBreakdownService")
public class CacheBreakdownServiceImpl extends ServiceImpl<CacheBreakdownDao, CacheBreakdownEntity> implements CacheBreakdownService {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CacheBreakdownEntity> page = this.page(
                new Query<CacheBreakdownEntity>().getPage(params),
                new QueryWrapper<CacheBreakdownEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public CacheBreakdownEntity getCacheBreakdownEntityById(String key) {
        //1 先从redis里面查询，如果有直接返回结果，如果没有再去查询mysql
        CacheBreakdownEntity cacheBreakdownEntity = (CacheBreakdownEntity) redisTemplate.opsForValue().get(key);

        if(Objects.isNull(cacheBreakdownEntity)) {
            //2 大厂用，对于高QPS的优化，进来就先加锁，保证一个请求操作，让外面的redis等待一下，避免击穿mysql
            synchronized (CacheBreakdownServiceImpl.class){
                cacheBreakdownEntity = (CacheBreakdownEntity) redisTemplate.opsForValue().get(key);
                //3 二次查redis还是null，可以去查mysql了(mysql默认有数据)
                if (Objects.isNull(cacheBreakdownEntity)) {
                    //4 查询mysql拿数据
                    cacheBreakdownEntity = this.getById(key);//mysql默认有数据
                    if (Objects.isNull(cacheBreakdownEntity)) {
                        return null;
                    }else{
                        //5 mysql里面有数据的，需要回写redis，完成数据一致性的同步工作
                        redisTemplate.opsForValue().setIfAbsent(key,cacheBreakdownEntity,1L, TimeUnit.DAYS);
                    }
                }
            }
        }

        return cacheBreakdownEntity;
    }

}